package com.wsj.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

/**
 * description:切面(Aspect)：包含横切逻辑和切入点的定义，Spring AOP就是负责实施切面的框架，它将切面所定义的横切逻辑织入到切面所指定的连接点中
 *
 * @author yang
 * @date 2019/2/19 10:40
 */
@Component
@Aspect
public class LogAspect {

  @Pointcut("execution(* com.wsj.services..*(..))")
  public void aspect() {
  }

  @Pointcut("@target(com.wsj.aop.anno.Log)")
  public void operationLog() {
  }

  /**
   * description: @Before("aspect()")：向注解处理方法传递参数
   *
   * @author yang
   * @date 2019/2/20 10:15
   */
  @Before("operationLog()")
  public void beforeLog(JoinPoint joinPoint) {
    System.out.println("============前置增强==============");
    Signature signature = joinPoint.getSignature();
    String className = joinPoint.getTarget().getClass().getName();
    String methodName = signature.getName();
    Object[] arguments = joinPoint.getArgs();
    //获取连接点所在的目标对象
    System.out.println("目标类：" + joinPoint.getTarget().getClass());
    System.out.println("代理类：" + joinPoint.getThis().getClass());
    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    String[] argumentNames = methodSignature.getParameterNames();
    StringBuilder sb = new StringBuilder(className + "，" + methodName + "(");
    for (int i = 0; i < arguments.length; i++) {
      Object argument = arguments[i];
      sb.append(argumentNames[i]).append("->").append(argument != null ? argument.toString() : "null");
    }
    sb.append(")");
    System.out.println("目标类和方法：" + sb.toString());
  }

  /**
   * description:@within()、@this()、@target()、@args()、@annotation、@bean，这些表达式是可以利用 ||, &&, ! 进行自由组合的
   *
   * @author yang
   * @date 2019/2/20 10:17
   */
  @After("operationLog()")
  public void afterLog() {
    System.out.println("==========后置增强============");
  }

  public Object roundAdvice(ProceedingJoinPoint p, String name) {
    System.out.println("=============环绕增强开始，name：" + name);
    Object o = null;
    try {
      o = p.proceed();
      Object[] args = p.getArgs();
      if (null != args) {
        for (Object arg : args) {
          System.out.println("==========环绕增强参数值：" + arg);
        }
      }
    } catch (Throwable e) {
      e.printStackTrace();
    }
    System.out.println("===================环绕增强结束，name：" + name);
    return o;

  }

}
